/*
* This file is part of RoboDS (http://code.google.com/p/robods/)
* Copyright (C) 2007 Blakharaz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/

#include "UserInterface.h"

#include "Card.h"
#include "Logger.h"
#include "Map.h"
#include "OkButton.h"
#include "Robot.h"
#include "Sprite.h"

namespace robo
{

UserInterface::UserInterface(Robot* robot)
:	RobotController(robot)
{
    for (int idx = 0; idx < 5; ++idx)
    {
        mSelectedCard[idx] = NULL;
    }

	for (int idx = 0; idx < 5; ++idx)
	{
		mSlots[idx].Top = 6;
		mSlots[idx].Bottom = 53;
		mSlots[idx].Left = 39 + 44*idx;
		mSlots[idx].Right = 71 + 44*idx;
	}
	mSlots[SLOT_AVAIL].Top = 67;
	mSlots[SLOT_AVAIL].Bottom = 122;
	mSlots[SLOT_AVAIL].Left = 37;
	mSlots[SLOT_AVAIL].Right = 249;

    mPowerButton = new Sprite(Sprite::SPRITE_POWER_BUTTON, 0);
    mPowerButton->setPosition(160, 128);
    PA_SetSpriteAnim(0, mPowerButton->createSprite(), 0);
 
    mOkButton = new OkButton();
    mOkButton->setPosition(192, 128);
	mOkButton->setEnabled(false);
}

UserInterface::~UserInterface()
{
}

void UserInterface::update()
{
    mMap->update();
    mRobot->update();

    // Draw the selected cards
    for (int idx = 0; idx < 5; ++idx)
    {
        if (mSelectedCard[idx])
        {
			mSelectedCard[idx]->setPosition(
				mSlots[idx].Left, 
				mSlots[idx].Top);
        }
    }

    // Draw the drawn cards
	static unsigned short CARD_WIDTH = 32;

	unsigned short cardDist = 
		mAvailableCards.size() <= 1 
		? 0
		: (mSlots[SLOT_AVAIL].Right - CARD_WIDTH - mSlots[SLOT_AVAIL].Left) 
			/ (mAvailableCards.size() - 1);

    unsigned short drawnIdx = 0;

	char buf[32];
	sprintf(buf, "%d-%d: %d", mSlots[SLOT_AVAIL].Right, mSlots[SLOT_AVAIL].Left, cardDist);
	Logger::getSingleton()->log(buf);

    for (CardSetSpritePrio::const_iterator it = mAvailableCards.begin();
        it != mAvailableCards.end(); ++it)
    {
		Sprite* cur = (*it);
		
        cur->setPosition(
			mSlots[SLOT_AVAIL].Right - CARD_WIDTH - drawnIdx * cardDist, 
			mSlots[SLOT_AVAIL].Top);

        drawnIdx++;
    }
}

void UserInterface::setMap(Map* map)
{
    mMap = map;
}

void UserInterface::setAvailableCards(const CardSetSpritePrio& availCards)
{
    mAvailableCards = availCards;
}

void UserInterface::addAvailableCard(Card* card)
{
    if (mAvailableCards.find(card) != mAvailableCards.end())
	{
		return;
	}

	for (int idx = 0; idx < 5; ++idx)
    {
        if (mSelectedCard[idx] == card)
        {
			mSelectedCard[idx] = NULL;
			break;
        }
    }

    mAvailableCards.insert(card);
	checkOkButton();
}

void UserInterface::removeAvailableCard(Card* card)
{
    CardSetSpritePrio::iterator it = mAvailableCards.find(card);
        
    if (it != mAvailableCards.end())
    {
		mAvailableCards.erase(it);
    }
}

void UserInterface::setActiveCard(int num, Card* card)
{
	if (mSelectedCard[num]) 
	{
		// switch cards

		bool switchSuccessful = false;

		for (int idx = 0; idx < 5; ++idx)
		{
			if (mSelectedCard[idx] == card)
			{
				mSelectedCard[idx] = mSelectedCard[num];
				switchSuccessful = true;
				break;
			}
		}

		if (!switchSuccessful)
		{
			addAvailableCard(mSelectedCard[num]);
		}
	}
	else
	{
		for (int idx = 0; idx < 5; ++idx)
		{
			if (mSelectedCard[idx] == card)
			{
				mSelectedCard[idx] = NULL;
				break;
			}
		}
	}


	removeAvailableCard(card);
	mSelectedCard[num] = card;
	checkOkButton();
}

Card* UserInterface::getActiveCard(int num)
{
	return mSelectedCard[num];
}

int UserInterface::getCardSlotAt(u16 x, u16 y)
{
	for (int idx = 0; idx <= 5; ++idx)
    {
		Rectangle r = mSlots[idx];
        if (r.Left <= x && x <= r.Right
			&& r.Top <= y && y <= r.Bottom)
        {
			return idx;
        }
    }

	return NO_SLOT;
}

void UserInterface::checkOkButton()
{
	bool okEnabled = true;
	for (int idx = 0; idx < 5; ++idx)
    {
		if (!mSelectedCard[idx])
		{
			okEnabled = false;
			break;
		}
	}

	mOkButton->setEnabled(okEnabled);
}

bool UserInterface::isPowerButton(Sprite* sprite) const
{
	return sprite == mPowerButton;
}

void UserInterface::togglePowerButton()
{
	if (mPowerEnabled)
	{
		mPowerEnabled = false;
		Logger::getSingleton()->log("Power disabled");
		PA_SetSpriteAnim(0, mPowerButton->createSprite(), 1);
	}
	else
	{
		mPowerEnabled = true;
		Logger::getSingleton()->log("Power enabled");
		PA_SetSpriteAnim(0, mPowerButton->createSprite(), 0);
	}
}

OkButton* UserInterface::getOkButton() const
{
	return mOkButton;
}

void UserInterface::clear() 
{
	///@todo move deletion of cards to central card management
	for (int i=0; i<5; ++i)
	{
		delete mSelectedCard[i];
		mSelectedCard[i] = NULL;
	}

	for (CardSetSpritePrio::iterator it = mAvailableCards.begin();
        it != mAvailableCards.end(); ++it)
    {
		delete *it;
	}
	mAvailableCards.clear();
}

}
